package com.da.landlord;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.da.finance.DaFinanceCategory;
import com.da.finance.DaFinanceStatement;
import com.da.finance.DaFinanceStatementService;
import com.espirit.eap.sa.LoginUser;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.GenericService;
import com.ra.external.FeeNotificationService;
import com.ra.external.RoomInfoService;
import com.ra.external.RoomRetrievalService;
import com.ra.external.WeixinUserService;
import com.ra.landlord.Agreement;
import com.ra.landlord.Fee;
import com.ra.landlord.FeeRecord;
import com.ra.landlord.LandlordAssistUser;
import com.ra.landlord.LandlordOwnerUser;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.Meter;
import com.ra.landlord.Room;
import com.ra.landlord.TenantUser;
import com.ra.landlord.ValidAgreement;
import com.ra.landlord.constant.LandlordConstant;
import com.ra.order.rental.RentalOrder;
import com.ra.order.rental.RentalOrderService;
import com.ra.util.DateTimeUtil;
import com.ra.weixin.WeixinUser;
import com.ra.wr.RoomInfoTdo;

/**
 * 此接是向外提供的接口 主要用于工作台调用 
 * @author Peter Z
 *
 */
@Service
public class DaRoomService {

	private static Logger logger = LoggerFactory.getLogger(DaRoomService.class);
	
	@Resource
	private GenericService genericService;

	@Resource
	private LandlordUserService landlordUserService;
	
	@Resource
	private RoomInfoService roomInfoService;
	
	@Resource
	private WeixinUserService weixinUserService;
	
	@Resource
	private FeeNotificationService notificationService;
	
	@Resource
	private RoomRetrievalService roomRetrievalService;
	
	@Resource
	private DaSuiteService suiteService;
	
	@Resource
	private DaChargeItemService chargeItemService;
	
	@Resource
	private DaFinanceStatementService financeStatementService;
	
	@Resource
	private PaidNoticeService paidNoticeService;
	
	@Resource
	private DaChargeBillRecordService chargeBillRecordService;
	
	@Resource
	private DaMeterService meterService;
	
	@Resource
	private RentalOrderService rentalOrderService;
	
	/**
	 * 获取相关数量方法 
	 * @param tag 1:该用户下的所有房间数
	 * @param tag 2:已收租/已缴费
	 * @param tag 3:未收租/未缴费
	 * @param tag 4:已出租
	 * @param tag 5:未出租/待租
	 * @param tag 6:合约已到期/已过期
	 * @param tag 7:有效合约数
	 * @return 具体数量 /-1表示非法参数 
	 */
	public Integer getCount(int tag){
		
		DaRoom room = new DaRoom();

		boolean diabledPermission = false;
		LandlordUser loginUser = landlordUserService.getLoginUser();
		if (loginUser instanceof LandlordAssistUser) 
		{
			DaSuite suite = new DaSuite();
			List<LandlordUser> assists = new ArrayList<LandlordUser>();
			assists.add(loginUser);
			suite.setLandlordUsers(assists);
			
			room.setSuite(suite);
			diabledPermission = true;
		} 
		
		PageInfo<DaRoom> page = genericService.searchByModel(room, Condition.DEFAULT, true, diabledPermission);
		List<DaRoom> lsRoom = page.getData();
		
		int receiptedCount = 0;  
		int waitReceiptCount = 0;	  
		
		int rentCount = 0;
		int waitRentCount = 0;
		
		int runsOutCount = 0;
		int runCount = 0;
		
		for (DaRoom daRoom : lsRoom) {
			if(daRoom.getRentState()!=null && daRoom.getRentState() == 0){
				rentCount++; 
				if(daRoom.getChargeItems().size()<=0){
					receiptedCount++; 
				}else{
					waitReceiptCount++;  
				}
				if(daRoom.getAgreement() != null && daRoom.getAgreement().getRentEndDate().compareTo(new Date()) <= 0){
					runsOutCount++;
				}else{
					runCount++;
				}
			}else{
				waitRentCount++; 
			}
		}
		switch (tag) {
			case 1:
				return lsRoom.size();
			case 2:
				return receiptedCount;
			case 3:
				return  waitReceiptCount;
			case 4:
				return rentCount;
			case 5:
				return waitRentCount;
			case 6:
				return runsOutCount;
			case 7:
				return runCount;
			default:
				return -1;
		}
		
	}
	
	/**
	 * 获取daRoom的最早合约开始时间
	 * @param daSuite
	 * @return
	 */
	@Rest(type = "search")
	public Date getEarliestAgreementDate(DaRoom daRoom){
		Date earliestDate = Calendar.getInstance().getTime();
		
		if(daRoom.getAgreement() == null){
			return earliestDate;
		}else{
			return daRoom.getAgreement().getRentBeginDate();
		}
	}
	
	//修正历史数据room的当前有效合约agreement字段
	public void correctRoomAgreement() {
		QLInfo qlInfo = new QLInfo("select a from " + DaRoom.class.getName() + " a where a.agreement.id is null and  a.rentState = " + DaRoom.RENT_STATE_RENT, true);
		List<DaRoom> rooms = genericService.searchByQl(qlInfo).getData();
		for (DaRoom room : rooms) {
			List<DaAgreement> agreements = room.getAgreements();
			for (DaAgreement agreement : agreements) {
				if (agreement.getAgreementState() == DaAgreement.AGREEMENT_STATE_VALID) {
					room.setAgreement(agreement);
					genericService.merge(room);
					break;
				}
			}
		}
	}
	
	private void processTenantUser(DaAgreement model) {
		TenantUser tenantUser = model.getTenantUser();
		TenantUser example = new TenantUser();
		TenantUser dbTenantUser = null;
		example.setPhone(tenantUser.getPhone().trim());
		example.setName(tenantUser.getName().trim());
		List<TenantUser> tenantUsers = genericService.searchByModel(example, Condition.DEFAULT).getData();
		if (tenantUsers.size() != 0) {
			dbTenantUser = tenantUsers.get(0);
		}
		if (dbTenantUser != null) {
			dbTenantUser.setGender(tenantUser.getGender());
			dbTenantUser.setAddress(tenantUser.getAddress());
			dbTenantUser.setPhotoFileName(tenantUser.getPhotoFileName());
			dbTenantUser.setIdCard(tenantUser.getIdCard());;
			model.setTenantUser(dbTenantUser);
		} else {
			model.getTenantUser().setId(null);
			tenantUser.setRegister(new Date());
			//tenantUser.setBirthday(DateTimeUtil.getBirthday(tenantUser.getIdCard()));
		}
		WeixinUser weixinUser = getWeixinUser(tenantUser.getPhone());
		if (weixinUser != null) {
			model.getTenantUser().setLoginUser(weixinUser.getLoginUser());
			model.getTenantUser().setRelatedWeixin(true);
		}
	}
	
	private DaRoom updateRoomOfAgreement(DaAgreement model, Integer rentState){
		// 修改房屋的状态
		DaRoom room = genericService.load(model.getRoom());
		room.setRentState(rentState);
		room.setRentPay(model.getRentPay().setScale(2,BigDecimal.ROUND_HALF_UP));
		/*suiteService.synSuiterentStatus(room.getSuite().getId());*/
		if (model.getDeposit() != null) {
			room.setDeposit(model.getDeposit().setScale(2, RoundingMode.HALF_UP));
		}
		return genericService.merge(room);
	}
	
	/**
	 * 根据租客电话获取微信用户
	 * @param phone
	 * @return
	 */
	@Rest(type = "search")
	public WeixinUser getWeixinUser(String phone){
		WeixinUser weixinUser = new WeixinUser();
		LoginUser loginUser = new LoginUser();
		loginUser.setName(phone);
		weixinUser.setLoginUser(loginUser);
		weixinUser = weixinUserService.getWeixinUser(weixinUser);
		return weixinUser;
	}
	
	public DaRoom _rent(DaRoom model) {
		return genericService.load(model);
	}
	
	public DaRoom _book(DaRoom model) {
		return genericService.load(model);
	}
	
	@Transactional
	public DaAgreement book(DaAgreement model) {
		processTenantUser(model);
		model.setLandlordUser(landlordUserService.getLoginUser().getOwnerUser());
		model.setBookPay(model.getBookPay().setScale(2, RoundingMode.HALF_UP));
		model.setRentPay(model.getRentPay().setScale(2, RoundingMode.HALF_UP));
		model.setAgreementState(DaAgreement.AGREEMENT_STATE_VALID);
		
		notificationService.indicateNotificationNeedRefresh();//房间出租情况变化后，定时发送短信列表需要更新
		DaAgreement dbAgreement = genericService.add(model);
		
		DaRoom dbRoom = updateRoomOfAgreement(dbAgreement, DaRoom.RENT_STATE_BOOK);
		dbRoom.setAgreement(dbAgreement);
		genericService.merge(dbRoom);
		roomRetrievalService.unPublishDaRoom(dbAgreement.getRoom());
		suiteService.synSuiterentStatus(dbRoom.getSuite().getId());
		return dbAgreement;
	}
	
	@Transactional
	public DaAgreement rent(DaAgreement model, List<DaMeter> meters) {
		processTenantUser(model);
		model.setLandlordUser(landlordUserService.getLoginUser().getOwnerUser());
		model.setDeposit(model.getDeposit().setScale(2, RoundingMode.HALF_UP));
		model.setBookPay(model.getBookPay().setScale(2, RoundingMode.HALF_UP));
		model.setRentPay(model.getRentPay().setScale(2, RoundingMode.HALF_UP));
		model.setAgreementState(DaAgreement.AGREEMENT_STATE_VALID);
		if (model.getAdvanceNum() == null) {
			model.setAdvanceNum(3);
		}
		
		notificationService.indicateNotificationNeedRefresh();//房间出租情况变化后，定时发送短信列表需要更新
		DaAgreement dbAgreement = genericService.merge(model);
		DaRoom dbRoom = updateRoomOfAgreement(model, DaRoom.RENT_STATE_RENT);
		genericService.refresh(dbAgreement.getRoom());
		roomRetrievalService.unPublishDaRoom(dbAgreement.getRoom());
		dbRoom.setAgreement(dbAgreement);
		genericService.merge(dbRoom);
		suiteService.synSuiterentStatus(dbRoom.getSuite().getId());
		chargeItemService.getOrGenerateChargeBillRecord(dbRoom);
		genericService.refresh(dbAgreement.getRoom());
		meterService.addMeters(meters);
		return dbAgreement;
	}
	
	@Transactional
	public DaChargeBillRecord _collectRental(DaRoom model) {
		DaRoom dbRoom = genericService.load(model);
		if (dbRoom.getAgreement() == null || DaRoom.RENT_STATE_RENT != dbRoom.getRentState()) {
			return null;
		}
		DaChargeBillRecord dbChargeBillRecord = chargeItemService.getOrGenerateChargeBillRecord(dbRoom);
		
		DaChargeBill example = new DaChargeBill();
		example.setAgreement(dbRoom.getAgreement());
		Condition condition = new Condition();
		condition.setSort("id");
		condition.setDir("desc");
		DaChargeBill dbChargeBill = genericService.searchByModel(example, condition).getData(0);
		if (dbChargeBill != null) {
			dbChargeBillRecord.setPrevBalance(dbChargeBill.getBalance());
			chargeItemService.generateSharedFixedChargeItems(dbRoom);
			dbChargeBillRecord.setCanChangeBeginDate(false);
		} else {
			dbChargeBillRecord.setPrevBalance(BigDecimal.valueOf(0).setScale(2));
			dbChargeBillRecord.setCanChangeBeginDate(true);
		}
		
		RentalOrder dbRentalOrder = rentalOrderService.searchRentalOrderByChargeBillRecord(dbChargeBillRecord);
		if (dbRentalOrder == null) {
			dbChargeBillRecord.setHasRentalOrder(false);
		} else {
			dbChargeBillRecord.setHasRentalOrder(true);
		}
		return dbChargeBillRecord;
	}
	
	public RentalOrder getRentalOrder(DaChargeBillRecord dbChargeBillRecord){
		RentalOrder example = new RentalOrder();
		example.setChargeBillRecord(dbChargeBillRecord);
		Condition condition = new Condition();
		condition.setSort("id");
		condition.setDir("desc");
		return genericService.searchByModel(example, condition).getData(0);
	}
	
	@Transactional
	public DaChargeBill collectRental(List<DaChargeItem> models, List<DaChargeItem> extraFee, Integer roomId, BigDecimal amountRecv, BigDecimal amountActual, String remark, Date dateBeginRecv, Date dateEndRecv, BigDecimal balance){
		DaRoom dbRoom = genericService.load(DaRoom.class, roomId);
		if (dbRoom == null) {
			throw new ApplicationException("房间找不到，收租失败！");	
		}
 		DaChargeBillRecord dbChargeBillRecord = chargeItemService.getOrGenerateChargeBillRecord(dbRoom);
		RentalOrder latestRentalOrder = getRentalOrder(dbChargeBillRecord);
		if (latestRentalOrder != null) {
			if (latestRentalOrder.getOrderState() == RentalOrder.ORDER_STATE_PAYING) { //int类型，可以直接比较
				throw new ApplicationException("该租客正在网上支付中，请稍后刷新未收租页面！");
			}else if(latestRentalOrder.getOrderState() == RentalOrder.ORDER_STATE_SUCCESS || latestRentalOrder.getOrderState() == RentalOrder.ORDER_STATE_PAYMENTED){
				throw new ApplicationException("该租客已网上支付，请刷新未收租页面！");
			}
		}
		dbChargeBillRecord.setStatus(DaChargeBillRecord.STATUS_RENT_DONE);
		dbChargeBillRecord.setAmountActual(amountActual);
		dbChargeBillRecord.setAmountRecv(amountRecv);
		dbChargeBillRecord.setBalance(balance);
		List<DaChargeItem> dbChargeItems = new ArrayList<DaChargeItem>();
		for (DaChargeItem chargeItem : models) {
			DaChargeItem dbChargeItem = genericService.load(chargeItem);
			dbChargeItem.setPriceActual(chargeItem.getPriceActual());
			dbChargeItem.setPriceRecv(chargeItem.getPriceRecv());
			if (DaChargeItem.CHARGE_TYPE_RENTAL.equals(dbChargeItem.getChargeType()) || DaChargeItem.CHARGE_TYPE_FIXED.equals(dbChargeItem.getChargeType()) || DaChargeItem.CHARGE_TYPE_CUSTOM.equals(dbChargeItem.getChargeType())) {
				dbChargeItem.setDateBeginRecv(dateBeginRecv);
				dbChargeItem.setDateEndRecv(dateEndRecv);
			}
			if (dbChargeItem.getChargeType() <= 1 || DaChargeItem.STATUS_CONFIRMED.equals(chargeItem.getStatus())) {	//目前为了跟ra统一，分散式也不支持押金和租金的勾选。
				dbChargeItem.setStatus(DaChargeItem.STATUS_PAID);	
			}
			dbChargeItem = genericService.merge(dbChargeItem);
			dbChargeItems.add(dbChargeItem);
		}
		if (extraFee != null && extraFee.size() > 0) {
			for (DaChargeItem chargeItem : extraFee) {
				DaChargeItem dbChargeItem = new DaChargeItem();
				dbChargeItem.setPriceActual(chargeItem.getPriceActual());
				dbChargeItem.setPriceRecv(chargeItem.getPriceActual()); //额外费用计算应收和实际应收一样
				dbChargeItem.setDateBeginRecv(dateBeginRecv);
				dbChargeItem.setDateEndRecv(dateEndRecv);
				dbChargeItem.setName(chargeItem.getName());
				dbChargeItem.setCreateChargeTime(new Date());
				dbChargeItem.setRoom(dbRoom);
				dbChargeItem.setChargeType(DaChargeItem.CHARGE_TYPE_CUSTOM);
				dbChargeItem.setChargeBillRecord(dbChargeBillRecord);
				dbChargeItem.setStatus(DaChargeItem.STATUS_PAID);
				dbChargeItem = genericService.merge(dbChargeItem);
				dbChargeItems.add(dbChargeItem);
			}
		}
		
		DaChargeBill chargeBill = new DaChargeBill();
		chargeBill.setRoom(dbRoom);
		chargeBill.setAgreement(dbRoom.getAgreement());
		chargeBill.setAmountRecv(amountRecv);
		chargeBill.setAmountActual(amountActual);
		if (balance == null) {
			chargeBill.setBalance(amountActual.subtract(amountRecv).setScale(2, RoundingMode.HALF_UP));
		} else {
			chargeBill.setBalance(balance.setScale(2, RoundingMode.HALF_UP));
		}
		chargeBill.setRemark(remark);
		chargeBill.setDateActual(new Date());
		chargeBill.setChargeItems(dbChargeItems);
		chargeBill.setLandlordUser(landlordUserService.getLandlordOwnerUser());
		DaChargeBill dbChargeBill = genericService.add(chargeBill);
		chargeItemService.generateChargeBillRecord(dbRoom);
		financeStatementService.addInternal(dbRoom, chargeBill.getAmountActual(), DaFinanceCategory.FINANCE_CATEGORY_RENT, new Date(), DaFinanceStatement.TRADE_TYPE_CRASH, remark);
		paidNoticeService.paidNoticeFrom(dbRoom);
		return dbChargeBill;
	}
	
	public DaAgreement _updateAgreement(DaAgreement model) {
		return genericService.load(model);
	}
	
	public DaAgreement _updateBookAgreement(DaAgreement model) {
		return genericService.load(model);
	}
	
	@Transactional
	public DaAgreement updateAgreement(DaAgreement model) {
		DaRoom dbRoom = genericService.load(model.getRoom());
		processTenantUser(model);
		updateRoomOfAgreement(model, dbRoom.getRentState());
		DaAgreement dbValidAgreement = dbRoom.getAgreement();
		if (Room.RENT_STATE_ALREADY.equals(dbRoom.getRentState())) {
			if (!dbValidAgreement.getRentBeginDate().equals(model.getRentBeginDate())) {
				//提示产生feerecord，重新计算
			}
			BigDecimal oldDeposit = dbValidAgreement.getDeposit();
			dbValidAgreement.setRentPay(model.getRentPay());
			dbValidAgreement.setDeposit(model.getDeposit().setScale(2, RoundingMode.HALF_UP));
			dbValidAgreement.setRentBeginDate(model.getRentBeginDate());
			dbValidAgreement.setRentEndDate(model.getRentEndDate());
			dbValidAgreement.setRentCycle(model.getRentCycle());
			dbValidAgreement.setBookPay(model.getBookPay().setScale(2, RoundingMode.HALF_UP));
			dbValidAgreement.setRentPeriod(model.getRentPeriod());
			dbValidAgreement.setRentCycleType(model.getRentCycleType());
			dbValidAgreement.setDepositNum(model.getDepositNum());
			dbValidAgreement.setPayNum(model.getPayNum());
			dbValidAgreement.setAdvanceNum(model.getAdvanceNum());
			dbValidAgreement.setRemark(model.getRemark());
			dbValidAgreement.setPhotoFileName(model.getPhotoFileName());
			chargeBillRecordService.updateChargeBillRecordFromAgreement(dbValidAgreement, oldDeposit);
		} else {
			dbValidAgreement.setRentBeginDate(model.getRentBeginDate());
			dbValidAgreement.setBookPay(model.getBookPay().setScale(2, RoundingMode.HALF_UP));
			dbValidAgreement.setRemark(model.getRemark());
		}
		dbValidAgreement.setTenantUser(model.getTenantUser());
		return genericService.merge(dbValidAgreement);
	}
	
	public Map<String, Object> _unRent(DaRoom model) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		DaRoom dbRoom = genericService.load(model);
		if (dbRoom != null) {
			resultMap.put("room", dbRoom);
			DaChargeBillRecord dbLastestChargeBillRecord = null;
			try {
				dbLastestChargeBillRecord = chargeItemService.getOrGenerateChargeBillRecord(dbRoom);
			}
			catch(Exception e) {
				logger.error("Fail to chargeItemService.getOrGenerateChargeBillRecord by dbRoom.id:" + dbRoom.getId(), e);
				e.printStackTrace();
			}
			
			if (dbLastestChargeBillRecord == null || DaChargeBillRecord.STATUS_RENT_DONE.equals(dbLastestChargeBillRecord.getStatus()) || dbLastestChargeBillRecord.getDateBeginRecv().compareTo(new Date()) > 0) {
				//不需要收(新需求，要收仪表费用)
				if (dbLastestChargeBillRecord.getChargeItems() != null) {
					List<DaChargeItem> chargeItems = new ArrayList<DaChargeItem>();
					for (DaChargeItem chargeItem : dbLastestChargeBillRecord.getChargeItems()) {
						if (DaChargeItem.CHARGE_TYPE_METER.equals(chargeItem.getChargeType())) {
							chargeItems.add(chargeItem);
						}
					}
					resultMap.put("chargeItems", chargeItems);
				}
			} else {
				resultMap.put("chargeItems", dbLastestChargeBillRecord.getChargeItems());
			}
			
			DaChargeBill example = new DaChargeBill();
			example.setAgreement(dbRoom.getAgreement());
			Condition condition = new Condition();
			condition.setSort("id");
			condition.setDir("desc");
			DaChargeBill dbChargeBill = genericService.searchByModel(example, condition).getData(0);
			if (dbChargeBill != null) {
				resultMap.put("balance", dbChargeBill.getBalance());
				resultMap.put("needAddDeposit", true);
			} else {
				resultMap.put("balance", BigDecimal.ZERO);
				resultMap.put("needAddDeposit", false);
			}
		}
		return resultMap;
	}
	
	@Transactional
	public DaChargeBill unRent(DaRoom model, List<DaChargeItem> chargeItems, BigDecimal amountRecv, BigDecimal amountActual, Date dateBeginRecv, Date dateEndRecv, String remark) {
		DaRoom dbRoom = genericService.load(model);
		if (dbRoom == null) {
			throw new ApplicationException("房间找不到，退租失败！");	
		}
		RentalOrder latestRentalOrder = null;
		try
		{
			latestRentalOrder = getRentalOrder(chargeItemService.getOrGenerateChargeBillRecord(dbRoom));
		}
		catch(Exception e)
		{
			logger.error("Fail to getRentalOrder by dbRoom.id:" + dbRoom.getId(), e);
			e.printStackTrace();
		}
		
		if (latestRentalOrder != null) {
			if (latestRentalOrder.getOrderState() == RentalOrder.ORDER_STATE_PAYING) { //int类型，可以直接比较
				throw new ApplicationException("该租客正在网上支付中，请稍后刷新退租页面！");
			}else if(latestRentalOrder.getOrderState() == RentalOrder.ORDER_STATE_SUCCESS || latestRentalOrder.getOrderState() == RentalOrder.ORDER_STATE_PAYMENTED){
				throw new ApplicationException("该租客已网上支付，请稍后刷新退租页面！");
			}
		}
		List<DaChargeItem> dbChargeItems = new ArrayList<DaChargeItem>();
		for (DaChargeItem chargeItem : chargeItems) {
			if (chargeItem.getId() == null) {
				chargeItem.setCreateChargeTime(new Date());
				chargeItem.setName("押金（退租）");
				chargeItem.setChargeType(DaChargeItem.CHARGE_TYPE_BACK_DEPOSIT);
				chargeItem.setDateBeginRecv(new Date());
				chargeItem.setDateEndRecv(new Date());
				chargeItem.setRoom(dbRoom);
				chargeItem.setStatus(DaChargeItem.STATUS_PAID);
				DaChargeItem dbChargeItem = genericService.add(chargeItem);
				dbChargeItems.add(dbChargeItem);
			} else {
				DaChargeItem dbChargeItem = genericService.load(chargeItem);
				if (!DaChargeItem.CHARGE_TYPE_METER.equals(dbChargeItem.getChargeType())) {
					dbChargeItem.setPriceRecv(chargeItem.getPriceRecv());
				}
				dbChargeItem.setPriceActual(chargeItem.getPriceActual());
				dbChargeItem.setStatus(DaChargeItem.STATUS_PAID);
				dbChargeItem = genericService.merge(dbChargeItem);
				dbChargeItems.add(dbChargeItem);
			}
		}
		
		DaChargeBill chargeBill = new DaChargeBill();
		chargeBill.setRoom(dbRoom);
		chargeBill.setAgreement(dbRoom.getAgreement());
		chargeBill.setAmountRecv(amountRecv.multiply(BigDecimal.valueOf(-1)));
		chargeBill.setAmountActual(amountActual.multiply(BigDecimal.valueOf(-1)));
		chargeBill.setBalance(amountActual.subtract(amountRecv).multiply(BigDecimal.valueOf(-1)));
		chargeBill.setRemark(remark);
		chargeBill.setDateActual(new Date());
		chargeBill.setChargeItems(dbChargeItems);
		chargeBill.setLandlordUser(landlordUserService.getLandlordOwnerUser());
		DaChargeBill dbChargeBill = genericService.add(chargeBill);
		
		//记录财务流水
		financeStatementService.addInternal(dbRoom, dbChargeBill.getAmountActual().multiply(BigDecimal.valueOf(-1)), DaFinanceCategory.FINANCE_CATEGORY_UNRENT, new Date(), DaFinanceStatement.TRADE_TYPE_CRASH, "退租:"+dbChargeBill.getRemark());
		roomRetrievalService.publishDaRoom(dbRoom, false);		//发布房源
		
		DaAgreement dbAgreement = dbRoom.getAgreement();
		dbAgreement.setAgreementState(DaAgreement.AGREEMENT_STATE_INVALID);
		genericService.merge(dbAgreement);
		dbRoom.setRentState(DaRoom.RENT_STATE_UNRENT);
		dbRoom.setAgreement(null);
		genericService.merge(dbRoom);
		suiteService.synSuiterentStatus(dbRoom.getSuite().getId());
		roomRetrievalService.publishDaRoom(dbAgreement.getRoom(), true);
		return dbChargeBill;
	}
	
	/**
	 * 查找DA房间
	 * @param daRoom
	 * @since 4.0
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<DaRoom> searchDaRooms(DaRoom daRoom){
		
		StringBuilder sb = new StringBuilder();
		QLInfo ql = new QLInfo();
		sb.append("select a from " + DaRoom.class.getName() + " a where a.rentState=? ");
		ql.addParam(daRoom.getRentState());
		sb.append("and a.landlordUser=?");
		ql.addParam(daRoom.getLandlordUser());
		ql.setQl(sb.toString());
		List<DaRoom> daRooms = genericService.searchByQl(ql).getData();
		return daRooms;
	}
}
